home *** CD-ROM | disk | FTP | other *** search
- ;* PRINTINC.ASM
- ;************************************************************************
- ;* *
- ;* PC Scheme/Geneva 4.00 Borland TASM code *
- ;* *
- ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* A recursive print routine *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Created by: John Jensen Date: 1985 *
- ;* Revision history: *
- ;* - 10 Feb 87: fixed problem printing circular data structs (tc) *
- ;* - 21 Jan 88: binary I/O uses line-length = 0 (rb) *
- ;* - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- ;* *
- ;* ``In nomine omnipotentii dei'' *
- ;************************************************************************
- IDEAL
- %PAGESIZE 60, 132
- MODEL medium
- LOCALS @@
-
- INCLUDE "scheme.ash"
-
- TEST_NUM EQU 8
- HEAPERR EQU -3
-
- DATASEG
-
- show DB SP_OUTPUT or SP_SEPARE
- ccount DW 0
-
- CODESEG
- ;***********************************************************************
- ; Print a single character to the file, and send a newline if necessary.
- ;***********************************************************************
- PROC C printchar, @@char:WORD
- inc [ccount]
- test [show], SP_OUTPUT
- jz @@ret
- call currspc ; check spaces remaining
- or ax, ax
- jle @@skip
- @@cometothinkofit:
- call givechar C, [@@char]
- jmp @@ret
- @@skip:
- test [pflags], PORT_BINARY
- jnz @@cometothinkofit
- mov ax, LF
- call givechar C, ax ; newline
- call iswhitespace C, [@@char]; after newline, print nonspaces
- test ax, ax
- jz @@cometothinkofit
- @@ret:
- ret
- ENDP printchar
-
- ;************************************************************************
- ; Wrap issues a newline if there are less than LEN spaces
- ; left on the current output line.
- ;************************************************************************
- PROC C wrap, @@len:WORD
- mov dx, [@@len]
- test [show], SP_OUTPUT
- jz @@ret
- call curr_col
- cmp ax, 1
- jle @@ret
- call currspc ; get the available spaces
- cmp ax, dx
- jge @@ret
- mov ax, LF ; issue a newline
- call givechar C, ax
- @@ret:
- ret
- ENDP wrap
-
- ;************************************************************************
- ; Print the string with length LEN, first sending a newline
- ; if necessary.
- ;************************************************************************
- PROC C printstr, @@string:WORD, @@len:WORD
- call wrap C, [@@len] ; check available spaces
- mov ax, [@@len]
- add [ccount], ax
- test [show], SP_OUTPUT
- je @@ret
- call gvchars C, [@@string], [@@len]
- @@ret:
- ret
- ENDP printstr
-
- ;************************************************************************
- ; Return number of spaces remaining on current line
- ;************************************************************************
- PROC currspc NEAR
- push es bx
- mov bx, [port_reg.page]
- ldpage es, bx
- mov bx, [port_reg.disp]
- mov ax, [(PORTDEF es:bx).ncols]
- test ax, ax ; line length defined?
- jnz @@defined
- mov ax, -1 ; no, return negative value
- jmp @@ret
- @@defined:
- sub ax, [(PORTDEF es:bx).curcol]
- @@ret:
- pop bx es
- ret
- ENDP currspc
-
- ;************************************************************************
- ; Return current column
- ;************************************************************************
- PROC curr_col NEAR
- push es bx
- mov bx, [port_reg.page]
- ldpage es, bx
- mov bx, [port_reg.disp]
- mov ax, [(PORTDEF es:bx).ncols]
- or ax, ax ; Maintaining column?
- jz @@ret
- mov ax, [(PORTDEF es:bx).curcol] ; Yes, get column and return
- @@ret:
- pop bx es
- ret
- ENDP curr_col
-
- ;************************************************************************
- ; The main print routine
- ;************************************************************************
- PROC C sprint USES si di, @@page:WORD, @@disp:WORD, @@portpage:WORD, @@portdisp:WORD
- mov [ccount], 0
- call ssetadr C, [@@portpage], [@@portdisp]
-
- mov bx, [port_reg.page] ; fix for random i/o - note a write has taken place
- ldpage es, bx
- mov si, [port_reg.disp]
- and [(PORTDEF es:si).pflags], NOT PORT_FLUSHED ; mark as modified
-
- call subsprint C, [@@page], [@@disp]
- mov ax, [ccount]
- ret
- ENDP sprint
-
- ;************************************************************************
- ;* Recursive local object printing *
- ;************************************************************************
- PROC C subsprint NEAR, @@page:WORD, @@disp:WORD
- DATASEG
- @@abort DB "[WARNING: Output aborted by SHIFT-BREAK]"
- LABEL @@abort_
- @@deep DB "#<DEEP!>"
- LABEL @@deep_
- CODESEG
- cmp [s_break], 0 ; check for SHIFT-BREAK
- je @@goahead
- @@dead:
- mov ax, LF
- call givechar C, ax
- mov ax, @@abort_ - @@abort
- lea bx, [@@abort]
- call printstr C, bx, ax ; display message
- xor ax, ax
- test [show], SP_OUTPUT
- jnz @@donthide
- add ax, 2
- @@donthide:
- call restart C, ax
-
- @@goahead:
- call stkspc ; check stack space
- cmp ax, 64 ; stack low?
- jge @@stackok
- mov ax, @@deep_ - @@deep
- lea bx, [@@deep]
- call printstr C, bx, ax ; print no deeper
- jmp @@ret
-
- @@stackok:
- shl [@@page], 1 ; adjust page number
- mov bx, [@@page]
- mov di, [WORD ptype+bx]
- jmp [@@branchtab+di]
- DATASEG
- LABEL @@branchtab WORD
- DW @@list ; [0] LISTTYPE
- DW @@fixnum ; [1] FIXTYPE
- DW @@flonum ; [2] FLOTYPE
- DW @@bignum ; [3] BIGTYPE
- DW @@symbol ; [4] SYMBTYPE
- DW @@string ; [5] STRTYPE
- DW @@array ; [6] ARYTYPE
- DW @@continuation ; [7] CONTTYPE
- DW @@closure ; [8] CLOSTYPE
- DW @@free ; [9] FREETYPE
- DW @@code ; [10] CODETYPE
- DW @@inline ; [11] I86TYPE
- DW @@port ; [12] PORTTYPE
- DW @@char ; [13] CHARTYPE
- DW @@environment ; [14] ENVTYPE
- CODESEG
- @@list:
- DATASEG
- @@nil DB "()"
- LABEL @@nil_
- CODESEG
- test bx, bx ; null page?
- jnz @@notnil
- mov ax, @@nil_ - @@nil
- lea bx, [@@nil]
- call printstr C, bx, ax
- jmp @@ret
- @@notnil:
- mov dx, '('
- call printchar C, dx
- mov bx, [@@page] ; Get page
- ldpage es, bx ; Get paragraph address of page
- mov si, [@@disp] ; dispacement
- @@listloop:
- push bx si
- xor dh, dh
- mov dl, [(LISTDEF es:si).car.page]
- shr dx, 1 ; Change to number for subsprint
- mov cx, [(LISTDEF es:si).car.disp]
- call subsprint C, dx, cx
- pop si bx
- ldpage es, bx
- mov bl, [(LISTDEF es:si).cdr.page]
- mov si, [(LISTDEF es:si).cdr.disp]
- test bx, bx ; more items in list?
- jz @@listdone
- push bx si
- mov dx, ' '
- call printchar C, dx
- pop si bx
- ldpage es, bx
- cmp [ptype+bx], LISTTYPE
- je @@listloop
- push bx si ; dotted list
- mov dx, '.'
- call printchar C, dx
- mov dx, ' '
- call printchar C, dx
- pop si bx
- shr bx, 1 ; corrected page number
- call subsprint C, bx, si
- @@listdone:
- mov dx, ')'
- call printchar C, dx
- jmp @@ret
-
- @@fixnum:
- mov ax, 5
- call malloc C, ax
- or ax, ax
- jz @@memerror
- push ax
- call fix2big C, [@@disp], ax ; change to bignum
- pop ax ; put buffer address in ax
- mov bx, 5 ; put length in bx
- jmp @@printint
-
- @@memerror:
- mov ax, HEAPERR ; memory not available
- call errmsg C, ax
- mov ax, -1 ; signal error
- jmp @@errorret
-
- @@flonum:
- LOCALFLO = 8
- sub sp, LOCALFLO
- ldpage es, bx
- mov si, [@@disp]
- fld [(FLODEF es:si).data]
- fstp [QWORD bp-LOCALFLO]
- call printflo C
- add sp, LOCALFLO
- jmp @@ret
-
- @@array:
- DATASEG
- @@arraystart DB "#("
- LABEL @@arraystart_
- CODESEG
- mov ax, @@arraystart_ - @@arraystart
- lea bx, [@@arraystart]
- call printstr C, bx, ax
-
- ldpage es, [@@page]
- mov si, [@@disp]
- mov cx, [(VECDEF es:si).len]
- sub cx, OFFSET (TYPE VECDEF).data+SIZE POINTER
- xor bx, bx
- @@arrayloop:
- cmp bx, cx
- jle @@nextarraycell
- jmp @@listdone
- @@nextarraycell:
- mov al, [(VECDEF es:si+bx).data.page]
- mov dx, [(VECDEF es:si+bx).data.disp]
- xor ah, ah
- shr ax, 1 ; Page number for subsprint
- push bx cx si
- call subsprint C, ax, dx
- pop si cx bx
- cmp bx, cx ; last element?
- jge @@arraylast
- push bx cx si
- mov dx, ' '
- call printchar C, dx
- pop si cx bx
- @@arraylast:
- add bx, SIZE POINTER
- ldpage es, [@@page]
- jmp @@arrayloop
-
- @@continuation:
- DATASEG
- @@contmsg DB "#<CONTINUATION>"
- LABEL @@contmsg_
- CODESEG
- mov ax, @@contmsg_ - @@contmsg
- lea bx, [@@contmsg]
- call printstr C, bx, ax
- jmp @@ret
-
- @@closure:
- DATASEG
- @@closmsg DB "#<PROCEDURE"
- LABEL @@closmsg_
- CODESEG
- mov ax, @@closmsg_ - @@closmsg
- lea bx, [@@closmsg]
- call printstr C, bx, ax
- ldpage es, [@@page] ; fetch information operand from closure object
- mov si, [@@disp]
- xor bh, bh
- mov bl, [(CLOSDEF es:si).info.page]
- mov si, [(CLOSDEF es:si).info.disp]
- @@closloop:
- ldpage es, bx
- or bx, bx ; nil ?
- je @@endoflist
- cmp [ptype+bx], LISTTYPE ; symbol ?
- jne @@endoflist
- mov bl, [(LISTDEF es:si).cdr.page]
- mov si, [(LISTDEF es:si).cdr.disp]
- jmp @@closloop
- @@endoflist:
- cmp [ptype+bx], SYMBTYPE
- jne @@closdone
- mov cx, [(SYMDEF es:si).len]
- sub cx, OFFSET (TYPE SYMDEF).buffer - 1
- push bx cx
- call malloc C, cx
- pop cx bx
- or ax, ax
- jne @@closallocok
- jmp @@memerror
- @@closallocok:
- push ax cx ; save fresh string space and length
- sar bx, 1
- call get_sym C, ax, bx, si ; get the symbol name
- mov dx, ' '
- call printchar C, dx
- pop cx ax
- push ax
- dec cx ; decrement length
- call printstr C, ax, cx
- pop ax
- call free C, ax
- @@closdone:
- mov dx, '>'
- call printchar C, dx
- jmp @@ret
-
- @@free:
- DATASEG
- @@freemsg DB "#<FREE>"
- LABEL @@freemsg_
- CODESEG
- mov ax, @@freemsg_ - @@freemsg
- lea bx, [@@freemsg]
- call printstr C, bx, ax
- jmp @@ret
-
- @@inline:
- DATASEG
- @@inlinemsg DB "#<INLINE>"
- LABEL @@inlinemsg_
- CODESEG
- mov ax, @@inlinemsg_ - @@inlinemsg
- lea bx, [@@inlinemsg]
- call printstr C, bx, ax
- jmp @@ret
-
- @@code:
- DATASEG
- @@codemsg DB "#<CODE>"
- LABEL @@codemsg_
- CODESEG
- mov ax, @@codemsg_ - @@codemsg
- lea bx, [@@codemsg]
- call printstr C, bx, ax
- jmp @@ret
-
- @@environment:
- DATASEG
- @@envmsg DB "#<ENVIRONMENT>"
- LABEL @@envmsg_
- CODESEG
- mov ax, @@envmsg_ - @@envmsg
- lea bx, [@@envmsg]
- call printstr C, bx, ax
- jmp @@ret
-
- @@symbol:
- mov ax, '|'
- mov cx, SIZE SYMDEF
- mov si, [@@disp]
- shr bx, 1 ; corrected page number
- call printatm C, bx, si, cx, ax
- jmp @@ret
-
- @@string:
- ldpage es, bx
- mov si, [@@disp]
- sstrlen cx, <es:si>, OVERHEAD
- sub cx, OFFSET (TYPE STRDEF).buffer
- add [ccount], cx
- test [show], SP_OUTPUT
- jnz @@putstring
- jmp @@ret
- @@putstring:
- test [show], SP_SEPARE
- jnz @@sepstring
-
- push cx si
- call wrap C, cx
- pop si cx
- xor bx, bx
- @@plainloop:
- cmp bx, cx
- jl @@plainmore
- jmp @@ret
- @@plainmore:
- cmp [s_break], 0 ; check for SHIFT-BREAK
- je @@plainok
- jmp @@dead
- @@plainok:
- ldpage es, [@@page]
- mov al, [(STRDEF es:si+bx).buffer]
- xor ah, ah
- push bx
- call givechar C, ax
- pop bx
- inc bx
- jmp @@plainloop
-
- @@sepstring:
- xor bx, bx
- mov dx, 2 ; at least 2 chars to add: ""
- @@scanstring:
- cmp bx, cx
- jge @@scandone
- mov al, [(STRDEF es:si+bx).buffer]
- inc bx
- cmp al, '\'
- je @@scanspecial
- cmp al, '"'
- jne @@scanstring
- @@scanspecial:
- inc dx
- jmp @@scanstring
- @@scandone:
- add [ccount], dx ; update this count, too
- add dx, cx ; total char count
- push cx si
- call wrap C, dx
- pop si cx
- mov ax, '"'
- call givechar C, ax
- xor bx, bx
- @@seploop:
- cmp bx, cx
- jge @@sepdone
- cmp [s_break], 0 ; check for SHIFT-BREAK
- je @@sepok
- jmp @@dead
- @@sepok:
- ldpage es, [@@page]
- mov dl, [(STRDEF es:si+bx).buffer]
- xor dh, dh
- inc bx
- push bx
- cmp dl, '\'
- je @@sepspecial
- cmp dl, '"'
- jne @@sepnormal
- @@sepspecial:
- mov ax, '\'
- push dx
- call givechar C, ax
- pop dx
- @@sepnormal:
- call givechar C, dx
- pop bx
- jmp @@seploop
- @@sepdone:
- mov ax, '"'
- call givechar C, ax
- jmp @@ret
-
- @@char:
- LOCALCHAR = 14
- mov cx, [@@disp]
- test [show], SP_SEPARE
- jz @@rawchar
- sub sp, LOCALCHAR ; allocate a buffer on the stack
- lea si, [bp-LOCALCHAR]
- mov [WORD si], '\#' ; check for a special multi-character character constant
- mov [BYTE si+2], cl
- mov [BYTE si+3], 0
- xor bx, bx
- @@multiloop:
- cmp bl, SPECIALCHARS*2 ; end of comparison?
- jl @@multimore
- mov bx, 3
- jmp @@stringchar
- @@multimore:
- mov di, [spchars+bx]
- cmp cl, [di] ; compare with special char
- je @@multifound
- inc bx
- inc bx
- jmp @@multiloop
-
- @@multifound:
- mov bx, 2 ; length is at least 2
- inc di
- @@multicopy:
- cmp [BYTE di], 0 ; end of string?
- je @@multiend
- mov al, [di]
- mov [si+bx], al ; move character by character
- inc bx
- inc di
- jmp @@multicopy
- @@multiend:
- mov [BYTE si+bx], 0
- @@stringchar:
- call printstr C, si, bx
- add sp, LOCALCHAR
- jmp @@ret
- @@rawchar:
- call printchar C, cx
- jmp @@ret
-
- @@bignum:
- ldpage es, bx
- mov si, [@@disp]
- mov ax, [(BIGDEF es:si).data.len]
- dec ax
- push ax
- call malloc C, ax ; allocate memory for divider
- or ax, ax
- jne @@bignumok
- @@bignumerror:
- pop ax ; thrash off
- jmp @@memerror
- @@bignumok:
- mov bx, [@@page]
- shr bx, 1
- push ax
- call copybig C, bx, si, ax ; copy bignum to buffer
- pop ax bx ; restore the size & bignum
- @@printint: ; here ax=bignum's address, bx=len
- push ax ; save the bignum's address
- mov ax, bx
- add ax, bx
- add ax, bx
- sub ax, 5
-
- call malloc C, ax ; allocate memory for char buffer
- or ax, ax
- je @@bignumerror
- pop bx ; get the bignum
- push bx ax ; save the bignum & char buffer
-
- call big2asc C, bx, ax ; convert bignum to char string
- pop bx
- push bx ; get a look at the char buffer
- call printstr C, bx, ax ; print the bignum
- pop ax
- call free C, ax
- pop ax
- call free C, ax
- jmp @@ret
-
- @@port:
- DATASEG
- @@portmsg DB "#<PORT>"
- LABEL @@portmsg_
- CODESEG
- mov ax, @@portmsg_ - @@portmsg
- lea bx, [@@portmsg]
- call printstr C, bx, ax
- @@ret:
- xor ax, ax ; no carry = success
- @@errorret:
- ret
- ENDP subsprint
-
- END